package id.mankel.commons.util;

import org.apache.commons.lang3.ArrayUtils;

/**
 * @author dongxi.li
 */
public class MkNumbers {

    /**
     * Latin numbers
     */
    public static final char[] DIGITS_NUMBER = {
            '0' , '1' , '2' , '3' , '4' , '5' ,
            '6' , '7' , '8' , '9'
    };

    /**
     * Lower case letters
     */
    public static final char[] DIGITS_LOWER_CASE = {
            'a' , 'b' ,
            'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
            'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
            'o' , 'p' , 'q' , 'r' , 's' , 't' ,
            'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    };

    /**
     * Upper case letters
     */
    public static final char[] DIGITS_UPPER_CASE = {
            'A' , 'B' ,
            'C' , 'D' , 'E' , 'F' , 'G' , 'H' ,
            'I' , 'J' , 'K' , 'L' , 'M' , 'N' ,
            'O' , 'P' , 'Q' , 'R' , 'S' , 'T' ,
            'U' , 'V' , 'W' , 'X' , 'Y' , 'Z'
    };

    /**
     * 62进制用的字符
     */
    private static final char[] DEFAULT_DIGITS = {
            '0' , '1' , '2' , '3' , '4' , '5' ,
            '6' , '7' , '8' , '9' ,

            'a' , 'b' ,
            'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
            'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
            'o' , 'p' , 'q' , 'r' , 's' , 't' ,
            'u' , 'v' , 'w' , 'x' , 'y' , 'z' ,

            'A' , 'B' ,
            'C' , 'D' , 'E' , 'F' , 'G' , 'H' ,
            'I' , 'J' , 'K' , 'L' , 'M' , 'N' ,
            'O' , 'P' , 'Q' , 'R' , 'S' , 'T' ,
            'U' , 'V' , 'W' , 'X' , 'Y' , 'Z'
    };

    /**
     * 把数字转换成对应进制的字符串
     * @param n 要被转换的数字
     * @param radix 基数，多少进制
     * @param digits 用到的字符
     * @return 对应进制的字符串
     */
    public static String toString(long n, int radix, char[] digits) {
        if (0 > n) {
            throw new IllegalArgumentException("negative number");
        }
        if (radix < Character.MIN_RADIX || radix > digits.length) {
            radix = digits.length;
        }

        byte[] buf = new byte[62];
        int charPos = 61;

        while (n >= radix) {
            buf[charPos--] = (byte) digits[(int) (n % radix)];
            n = n / radix;
        }
        buf[charPos] = (byte) digits[(int) n];

        return new String(buf, charPos, (buf.length - charPos));
    }

    /**
     * @see MkNumbers#toString(long, int, char[])
     */
    public static String toString(int i, int radix) {
        return toString(i, radix, DEFAULT_DIGITS);
    }

    /**
     * @see MkNumbers#toString(long, int, char[])
     */
    public static String toString(long i, int radix) {
        return toString(i, radix, DEFAULT_DIGITS);
    }

    /**
     * 把字符串转换成对应进制的数字
     * @param s 要被转换的字符串
     * @param radix 基数，多少进制
     * @param digits 用到的字符
     * @return 对应进制的数字
     */
    public static long parseLong(String s, int radix, char[] digits) {
        long l = 0;
        char[] chars = s.toCharArray();
        ArrayUtils.reverse(chars);
        for (int i = 0, n; i < chars.length; i++) {
            n = ArrayUtils.indexOf(digits, chars[i]);
            if (-1 == n) {
                throw new IllegalArgumentException("unsupported char");
            }
            l += n * Math.pow(radix, i);
        }
        return l;
    }

    /**
     * @see MkNumbers#parseLong(String, int, char[])
     */
    public static long parseLong(String s, int radix) {
        return parseLong(s, radix, DEFAULT_DIGITS);
    }

    /**
     * @see MkNumbers#parseLong(String, int, char[])
     */
    public static int parseInt(String s, int radix) {
        return (int) parseLong(s, radix);
    }

}
